package com.tgjorgoski.spellcheck;

import com.swabunga.spell.engine.Word;
import com.swabunga.spell.event.SpellCheckEvent;
import com.tgjorgoski.window.Session;

import javax.swing.*;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


public class JSpellForm extends JPanel implements ActionListener, ListSelectionListener {
  /** The Ignore button click action command*/
  public static final String IGNORE_CMD = "IGNORE";
  /** The Ignore All button click action command*/
  public static final String IGNOREALL_CMD = "IGNOREALL";
  /** The Add button click action command*/
  public static final String ADD_CMD = "ADD";
  /** The Replace button click action command*/
  public static final String REPLACE_CMD = "REPLACE";
  /** The Replace All button click action command*/
  public static final String REPLACEALL_CMD = "REPLACEALL";
  /** The Cancel button click action command*/
  public static final String CANCEL_CMD = "CANCEL";
  
  private JLabel wrongWordLabel;

  /* Accessible GUI Components */
  protected JList suggestList;
  protected JTextField checkText;
  /* The current spell check event */
  protected SpellCheckEvent spellEvent;
  /** The listener list (holds actionlisteners) */
  protected EventListenerList listenerList = new EventListenerList();

  /** Panel constructor */
  public JSpellForm() {
    initialiseGUI();
  }

  /** Helper method to create a JButton with a command, a text label and a listener*/
  private static final JButton createButton(String command, String text, ActionListener listener) {
    JButton btn = new JButton(text);
    btn.setActionCommand(command);
    btn.addActionListener(listener);
    return btn;
  }

  protected JPanel makeRightPanel() {
    JPanel jPanel1 = new JPanel();
    BoxLayout layout = new BoxLayout(jPanel1, BoxLayout.Y_AXIS);
    jPanel1.setLayout(layout);

    JButton ignoreBtn = createButton(IGNORE_CMD, "Ignore", this);
    ignoreBtn.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
    jPanel1.add(ignoreBtn);

    JButton ignoreAllBtn = createButton(IGNOREALL_CMD, "Ignore All", this);
    ignoreAllBtn.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
    jPanel1.add(ignoreAllBtn);

    JButton addBtn = createButton(ADD_CMD, "Add to Dictionary", this);
    addBtn.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
    jPanel1.add(addBtn);

    JButton changeBtn = createButton(REPLACE_CMD, "Change", this);
    changeBtn.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
    jPanel1.add(changeBtn);

    JButton changeAllBtn = createButton(REPLACEALL_CMD, "Change All", this);
    changeAllBtn.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
    jPanel1.add(changeAllBtn);

    JButton cancelBtn = createButton(CANCEL_CMD, "Cancel", this);
    cancelBtn.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
    jPanel1.add(cancelBtn);

    return jPanel1;
  }

  protected JPanel makeCentrePanel() {
    JPanel jPanel2 = new JPanel();
    jPanel2.setLayout(new BoxLayout(jPanel2, BoxLayout.Y_AXIS));
    JPanel jPanel3 = new JPanel();
    JLabel lbl1 = new JLabel("Not in Dictionary");
    wrongWordLabel = new JLabel("");
    wrongWordLabel.setForeground(Color.red); //Changed Color.RED to Color.red for 1.3 compatibility.
    jPanel3.add(lbl1);
    jPanel3.add(wrongWordLabel);
    jPanel2.add(jPanel3);
    checkText = new JTextField();
    jPanel2.add(checkText);
    JLabel lbl2 = new JLabel("Suggestions");
    jPanel2.add(lbl2);
    suggestList = new JList();
    suggestList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    jPanel2.add(new JScrollPane(suggestList));
    suggestList.addListSelectionListener(this);
    return jPanel2;
  }

  /** Called by the constructor to initialise the GUI*/
  protected void initialiseGUI() {
    setLayout(new BorderLayout());
    this.add(makeRightPanel(), BorderLayout.EAST);
    this.add(makeCentrePanel(), BorderLayout.CENTER);
  }

  /** Register an action listener */
  public void addActionListener(ActionListener l) {
    listenerList.add(ActionListener.class, l);
  }

  /** Deregister an action listener*/
  public void removeActionListener(ActionListener l) {
    listenerList.remove(ActionListener.class, l);
  }

  protected void fireActionEvent(ActionEvent e) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length - 2; i >= 0; i -= 2) {
      if (listeners[i] == ActionListener.class) {
        ((ActionListener) listeners[i + 1]).actionPerformed(e);
      }
    }
  }

  /** Sets the current spell check event that is being shown to the user*/
  public void setSpellEvent(SpellCheckEvent event) {
    spellEvent = event;
    DefaultListModel m = new DefaultListModel();
    java.util.List suggestions = event.getSuggestions();
    for (int i = 0; i < suggestions.size(); i++) {
      m.addElement(suggestions.get(i));
    }
    suggestList.setModel(m);
    wrongWordLabel.setText(event.getInvalidWord());
    if (m.size() > 0) {
      suggestList.setSelectedIndex(0);
      checkText.setText(((Word) m.get(0)).getWord());
    } else {
      checkText.setText(event.getInvalidWord());
    }
  }

  /** Fired when a value in the list is selected*/
  public void valueChanged(ListSelectionEvent e) {
    if (!e.getValueIsAdjusting()) {
      Object selectedValue = suggestList.getSelectedValue();
      if (selectedValue != null)
        checkText.setText(selectedValue.toString());
    }
  }

  /** Fired when a button is selected */
  public void actionPerformed(ActionEvent e) {
    if (IGNORE_CMD.equals(e.getActionCommand())) {
        spellEvent.ignoreWord(false);
    } else if (IGNOREALL_CMD.equals(e.getActionCommand())) {
        SpellcheckDictionaries.ignoreWord(spellEvent.getInvalidWord());
        spellEvent.ignoreWord(false);
    } else if (REPLACE_CMD.equals(e.getActionCommand())) {
      spellEvent.replaceWord(checkText.getText(), false);
    } else if (REPLACEALL_CMD.equals(e.getActionCommand())) {
      spellEvent.replaceWord(checkText.getText(), true);
    } else if (ADD_CMD.equals(e.getActionCommand())) {
      String inField = checkText.getText();
      Object selObj = suggestList.getSelectedValue();
      String selected = (selObj == null ? "" : selObj.toString());
      String addString = (inField.equals(selected) ? spellEvent.getInvalidWord() : inField);

      int n = JOptionPane.showConfirmDialog(Session.getHTMLView(), "Add '" + addString + "' to dictionary", "Add Word?", JOptionPane.YES_NO_OPTION);

      if (n == JOptionPane.YES_OPTION) {
        spellEvent.addToDictionary(addString);
        SpellcheckDictionaries.fireUserDictionaryModified();
      } else {
        return;
      }
    } else if (CANCEL_CMD.equals(e.getActionCommand())) {
      spellEvent.cancel();
    }
    fireActionEvent(e);
  }
 
}



